package com.harmony.pilot.completion.service.impl;

import com.harmony.pilot.common.constants.ServiceConstants;
import com.harmony.pilot.common.dto.*;
import com.harmony.pilot.completion.service.CompletionService;
import com.harmony.pilot.completion.client.DataServiceClient;
import com.harmony.pilot.completion.client.LLMServiceClient;
import com.harmony.pilot.completion.client.BuildServiceClient;
import com.harmony.pilot.completion.client.FunctionImplementationClient;
import com.harmony.pilot.completion.client.CompilationDatabaseClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.harmony.pilot.common.dto.FunctionImplementation;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 代码补全服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CompletionServiceImpl implements CompletionService {
    
    private final DataServiceClient dataServiceClient;
    private final LLMServiceClient llmServiceClient;
    private final BuildServiceClient buildServiceClient;
    private final FunctionImplementationClient functionImplementationClient;
    private final CompilationDatabaseClient compilationDatabaseClient;
    
    @Override
    @Cacheable(value = "completions", key = "#request.context.filePath + '-' + #request.context.cursorLine")
    public List<CompletionItem> getCompletions(CompletionRequest request) {
        CodeContext context = request.getContext();
        List<CompletionItem> items = new ArrayList<>();
        
        // 1. 从CodeQL获取静态补全
        try {
            List<CompletionItem> staticItems = dataServiceClient.querySymbols(context);
            
            // 增强补全：为函数补全项添加实现信息
            for (CompletionItem item : staticItems) {
                if (ServiceConstants.KIND_FUNCTION.equals(item.getKind()) || 
                    ServiceConstants.KIND_METHOD.equals(item.getKind())) {
                    enhanceCompletionWithImplementation(item, context);
                }
            }
            
            items.addAll(staticItems);
            log.debug("Got {} static completions from CodeQL", staticItems.size());
        } catch (Exception e) {
            log.warn("Failed to get static completions", e);
        }
        
        // 1.5. 使用编译数据库增强补全（如果可用）
        try {
            CompilationDatabaseClient.CompilationCommand cmd = 
                compilationDatabaseClient.queryCompilationCommand(
                    context.getFilePath(),
                    context.getProjectRoot()
                );
            
            if (cmd != null) {
                // 使用编译命令信息增强补全
                enhanceCompletionsWithCompilationDatabase(items, cmd, context);
                log.debug("Enhanced completions with compilation database");
            }
        } catch (Exception e) {
            log.debug("Compilation database not available or failed", e);
        }
        
        // 2. 从Neo4j获取基于调用关系的补全
        try {
            List<CompletionItem> graphItems = dataServiceClient.queryRelatedSymbols(context);
            items.addAll(graphItems);
            log.debug("Got {} graph-based completions from Neo4j", graphItems.size());
        } catch (Exception e) {
            log.warn("Failed to get graph completions", e);
        }
        
        // 3. 从构建系统获取依赖相关补全
        try {
            BuildInfo buildInfo = buildServiceClient.getBuildInfo(context.getProjectRoot());
            List<CompletionItem> buildItems = extractCompletionsFromBuild(buildInfo);
            items.addAll(buildItems);
            log.debug("Got {} completions from build system", buildItems.size());
        } catch (Exception e) {
            log.warn("Failed to get build completions", e);
        }
        
        // 4. 使用LLM增强补全
        if (request.getUseLLM() != null && request.getUseLLM()) {
            try {
                List<CompletionItem> llmItems = llmServiceClient.enhanceCompletions(context, items);
                items.addAll(llmItems);
                log.debug("Got {} LLM-enhanced completions", llmItems.size());
            } catch (Exception e) {
                log.warn("Failed to get LLM completions", e);
            }
        }
        
        // 5. 去重、排序、限制数量
        return items.stream()
                .distinct()
                .sorted((a, b) -> {
                    // 按置信度和排序优先级排序
                    double scoreA = (a.getConfidence() != null ? a.getConfidence() : 0.5) 
                                    * (100 - (a.getSortOrder() != null ? a.getSortOrder() : 50));
                    double scoreB = (b.getConfidence() != null ? b.getConfidence() : 0.5) 
                                    * (100 - (b.getSortOrder() != null ? b.getSortOrder() : 50));
                    return Double.compare(scoreB, scoreA);
                })
                .limit(request.getMaxResults())
                .collect(Collectors.toList());
    }
    
    /**
     * 增强补全项：添加函数实现信息
     * 当用户调用其他模块的函数时，提供函数实现、参数类型、返回值等信息
     */
    private void enhanceCompletionWithImplementation(CompletionItem item, CodeContext context) {
        try {
            // 从补全项中提取函数信息
            String functionName = extractFunctionName(item.getLabel());
            String qualifiedName = extractQualifiedName(item);
            
            // 查找函数实现
            FunctionImplementation impl = functionImplementationClient.findFunctionImplementation(
                functionName,
                qualifiedName,
                context.getFilePath()
            );
            
            if (impl != null && impl.getSymbol() != null) {
                // 增强补全项的详细信息
                enhanceCompletionItem(item, impl);
            }
            
        } catch (Exception e) {
            log.debug("Failed to enhance completion with implementation", e);
        }
    }
    
    /**
     * 从补全项标签中提取函数名
     */
    private String extractFunctionName(String label) {
        if (label == null) {
            return null;
        }
        
        // 提取函数名（去掉参数部分）
        int parenIndex = label.indexOf('(');
        if (parenIndex > 0) {
            String namePart = label.substring(0, parenIndex).trim();
            // 去掉命名空间和类名
            int lastColon = namePart.lastIndexOf("::");
            if (lastColon >= 0) {
                return namePart.substring(lastColon + 2);
            }
            return namePart;
        }
        return label;
    }
    
    /**
     * 从补全项中提取完整限定名
     */
    private String extractQualifiedName(CompletionItem item) {
        // 从detail或documentation中提取
        if (item.getDetail() != null) {
            // 尝试从detail中提取限定名
            String detail = item.getDetail();
            if (detail.contains("::")) {
                return detail;
            }
        }
        return null;
    }
    
    /**
     * 增强补全项信息
     */
    private void enhanceCompletionItem(CompletionItem item, FunctionImplementation impl) {
        // 添加返回值类型信息
        if (impl.getReturnType() != null && !impl.getReturnType().isEmpty()) {
            if (item.getDetail() == null || item.getDetail().isEmpty()) {
                item.setDetail(impl.getReturnType() + " " + item.getLabel());
            } else if (!item.getDetail().contains(impl.getReturnType())) {
                item.setDetail(impl.getReturnType() + " " + item.getDetail());
            }
        }
        
        // 添加参数信息
        if (impl.getParameters() != null && !impl.getParameters().isEmpty()) {
            StringBuilder paramInfo = new StringBuilder();
            paramInfo.append("参数: ");
            for (int i = 0; i < impl.getParameters().size(); i++) {
                if (i > 0) paramInfo.append(", ");
                paramInfo.append(impl.getParameters().get(i));
            }
            
            // 添加到文档中
            if (item.getDocumentation() == null) {
                item.setDocumentation(paramInfo.toString());
            } else {
                item.setDocumentation(item.getDocumentation() + "\n\n" + paramInfo.toString());
            }
        }
        
        // 添加实现代码片段（前几行）
        if (impl.getImplementationCode() != null && !impl.getImplementationCode().isEmpty()) {
            String codeSnippet = extractCodeSnippet(impl.getImplementationCode(), 10);
            if (codeSnippet != null && !codeSnippet.isEmpty()) {
                String codeDoc = "实现代码:\n```cpp\n" + codeSnippet + "\n```";
                if (item.getDocumentation() == null) {
                    item.setDocumentation(codeDoc);
                } else {
                    item.setDocumentation(item.getDocumentation() + "\n\n" + codeDoc);
                }
            }
        }
        
        // 添加调用者信息（了解使用场景）
        if (impl.getCallers() != null && !impl.getCallers().isEmpty()) {
            String callersInfo = "使用示例: " + String.join(", ", impl.getCallers().subList(0, 
                Math.min(3, impl.getCallers().size())));
            if (item.getDocumentation() == null) {
                item.setDocumentation(callersInfo);
            } else {
                item.setDocumentation(item.getDocumentation() + "\n\n" + callersInfo);
            }
        }
        
        // 提高置信度（有实现信息的补全更可靠）
        if (item.getConfidence() == null || item.getConfidence() < 0.9) {
            item.setConfidence(0.9);
        }
    }
    
    /**
     * 提取代码片段（前N行）
     */
    private String extractCodeSnippet(String code, int maxLines) {
        if (code == null || code.isEmpty()) {
            return null;
        }
        
        String[] lines = code.split("\n");
        StringBuilder snippet = new StringBuilder();
        for (int i = 0; i < Math.min(maxLines, lines.length); i++) {
            snippet.append(lines[i]).append("\n");
        }
        
        if (lines.length > maxLines) {
            snippet.append("...");
        }
        
        return snippet.toString();
    }
    
    /**
     * 使用编译数据库增强补全
     */
    private void enhanceCompletionsWithCompilationDatabase(
            List<CompletionItem> items,
            CompilationDatabaseClient.CompilationCommand cmd,
            CodeContext context) {
        
        // 1. 使用include路径过滤和排序补全项
        List<String> includePaths = cmd.getIncludePaths();
        if (includePaths != null && !includePaths.isEmpty()) {
            // 根据include路径调整补全项的置信度
            for (CompletionItem item : items) {
                if (item.getDetail() != null && item.getDetail().contains("#include")) {
                    // 如果补全项在include路径中，提高置信度
                    for (String includePath : includePaths) {
                        if (item.getDetail().contains(includePath)) {
                            item.setConfidence(item.getConfidence() != null ? 
                                Math.min(1.0, item.getConfidence() + 0.1) : 0.9);
                            break;
                        }
                    }
                }
            }
        }
        
        // 2. 使用宏定义信息
        List<String> defines = cmd.getDefines();
        if (defines != null && !defines.isEmpty()) {
            // 可以根据宏定义调整补全建议
            // 例如：如果定义了DEBUG，优先显示调试相关的API
            for (String define : defines) {
                if (define.startsWith("DEBUG") || define.contains("DEBUG")) {
                    // 提高调试相关补全的优先级
                    for (CompletionItem item : items) {
                        if (item.getLabel() != null && 
                            (item.getLabel().toLowerCase().contains("debug") ||
                             item.getLabel().toLowerCase().contains("log"))) {
                            item.setConfidence(item.getConfidence() != null ? 
                                Math.min(1.0, item.getConfidence() + 0.05) : 0.85);
                        }
                    }
                }
            }
        }
        
        // 3. 使用编译器选项
        CompilationDatabaseClient.CompilerOptions options = cmd.getCompilerOptions();
        if (options != null && options.getStd() != null) {
            // 根据C++标准版本调整补全
            // 例如：C++17支持的特性
            String std = options.getStd();
            if (std.contains("17") || std.contains("20")) {
                // 可以添加C++17/20特性的补全
            }
        }
    }
    
    @Override
    public List<CompletionItem> getFunctionCompletions(CompletionRequest request) {
        List<CompletionItem> allCompletions = getCompletions(request);
        
        // 只返回函数类型的补全
        return allCompletions.stream()
                .filter(item -> ServiceConstants.KIND_FUNCTION.equals(item.getKind()) 
                             || ServiceConstants.KIND_METHOD.equals(item.getKind()))
                .collect(Collectors.toList());
    }
    
    @Override
    public List<CompletionItem> getGnCompletions(CompletionRequest request) {
        List<CompletionItem> items = new ArrayList<>();
        
        try {
            // 从构建服务获取GN相关补全
            List<CompletionItem> gnItems = buildServiceClient.getGnCompletions(request.getContext());
            items.addAll(gnItems);
            
            // 添加常用的GN关键字和模板
            items.addAll(getGnKeywords());
            items.addAll(getGnTemplates());
            
        } catch (Exception e) {
            log.error("Failed to get GN completions", e);
        }
        
        return items.stream()
                .limit(request.getMaxResults())
                .collect(Collectors.toList());
    }
    
    /**
     * 从构建信息中提取补全项
     */
    private List<CompletionItem> extractCompletionsFromBuild(BuildInfo buildInfo) {
        List<CompletionItem> items = new ArrayList<>();
        
        if (buildInfo == null) {
            return items;
        }
        
        // 从依赖中提取可能的类和函数
        if (buildInfo.getDeps() != null) {
            buildInfo.getDeps().forEach(dep -> {
                items.add(CompletionItem.builder()
                        .label(dep)
                        .kind(ServiceConstants.KIND_CLASS)
                        .detail("From dependency")
                        .insertText(dep)
                        .source("build")
                        .confidence(0.6)
                        .build());
            });
        }
        
        return items;
    }
    
    /**
     * 获取GN关键字补全
     */
    private List<CompletionItem> getGnKeywords() {
        String[] keywords = {
            "executable", "shared_library", "static_library", "source_set",
            "action", "action_foreach", "group", "template",
            "sources", "deps", "public_deps", "data_deps",
            "include_dirs", "public_configs", "configs",
            "cflags", "cflags_cc", "ldflags", "defines"
        };
        
        List<CompletionItem> items = new ArrayList<>();
        for (String keyword : keywords) {
            items.add(CompletionItem.builder()
                    .label(keyword)
                    .kind(ServiceConstants.KIND_KEYWORD)
                    .detail("GN keyword")
                    .insertText(keyword)
                    .source("static")
                    .confidence(0.9)
                    .sortOrder(10)
                    .build());
        }
        return items;
    }
    
    /**
     * 获取GN模板补全
     */
    private List<CompletionItem> getGnTemplates() {
        List<CompletionItem> items = new ArrayList<>();
        
        // executable模板
        items.add(CompletionItem.builder()
                .label("executable")
                .kind(ServiceConstants.KIND_SNIPPET)
                .detail("Create executable target")
                .insertText("executable(\"${1:target_name}\") {\n  sources = [\n    \"${2:main.cpp}\",\n  ]\n  deps = []\n}")
                .isSnippet(true)
                .source("template")
                .confidence(0.95)
                .sortOrder(5)
                .build());
        
        // shared_library模板
        items.add(CompletionItem.builder()
                .label("shared_library")
                .kind(ServiceConstants.KIND_SNIPPET)
                .detail("Create shared library target")
                .insertText("shared_library(\"${1:lib_name}\") {\n  sources = [\n    \"${2:source.cpp}\",\n  ]\n  deps = []\n  public_configs = []\n}")
                .isSnippet(true)
                .source("template")
                .confidence(0.95)
                .sortOrder(5)
                .build());
        
        return items;
    }
}

